iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Software Development

我是Java工程師,關於密碼學我想懂的不多系列 第 9

Day08 - 現代密碼學基礎 -- 單向雜湊函數

  • 分享至 

  • xImage
  •  

一、 什麼是雜湊函數?(資料的數位指紋)

單向雜湊函數(One-Way Hash Function) 是一種能將「任意長度輸入資料」轉換成「固定長度字串輸出」的數學演算法。這個產出的固定長度字串通常稱為雜湊值(Hash Value)訊息摘要(Message Digest)

在密碼學中,我們常把雜湊值比喻為資料的「數位指紋(Digital Fingerprint)」,它具備以下三大基本物理特性:

  • 固定長度(Fixed-length Output):無論輸入資料多龐大,同一種演算法輸出的位元長度永遠固定(例如 SHA-256 永遠輸出 256 bits / 64 個字元的十六進位字串)。
  • 確定性(Deterministic):只要輸入資料完全相同,產出的雜湊值就保證 100% 相同。
  • 雪崩效應(Avalanche Effect):即使輸入資料只更動了極微小的 1 個 bit(例如將句號改成驚嘆號),輸出的雜湊值也會發生巨大且不可預測的劇烈變動(通常超過 50% 的位元發生改變)。

二、 密碼學雜湊函數的三大核心安全屬性

並非所有的雜湊演算法(例如用於 Hash Table 資料結構或 Java 內建的 Object.hashCode())都能用於安全領域。一個合格的密碼學雜湊函數必須嚴格滿足以下三種計算上的不可逆與抗碰撞特性:

1. 抗原像性(Pre-image Resistance / 單向性)

  • 數學概念:給定任意雜湊值 H,要逆向推算解出原始輸入 X(使得 h(X) = H),在計算複雜度上是不可能的。

2. 抗第二原像性(Second Pre-image Resistance / 弱抗碰撞性)

  • 數學概念:給定一個已知輸入 X1,要找到另一個不同的輸入 X2(滿足 X1 != X2),且兩者的雜湊值相同(h(X1) = h(X2)),在計算上是不可能的。

3. 抗碰撞性(Collision Resistance / 強抗碰撞性)

  • 數學概念:要尋找到「任意」兩個不同的輸入 X1 與 X2(滿足 X1 != X2),使其雜湊值完全相同(h(X1) = h(X2)),在計算上是不可能的。

三、 經典與現代雜湊演算法演進概觀

演算法 輸出長度 目前安全性狀態 技術說明與歷史現況
MD5 128 bits 完全破譯(極度危險) 已能在數秒內製造碰撞,嚴重不安全,已被全面廢除
SHA-1 160 bits 已遭破譯(禁止使用) Google 於 2017 年展現 SHAttered 實體碰撞攻擊,已淘汰。
SHA-2 224 / 256 / 384 / 512 bits 目前主流業界標準 包含 SHA-256 與 SHA-512,屬於 Merkle-Damgård 結構,目前無有效攻擊法。
SHA-3 224 / 256 / 384 / 512 bits 最新 NIST 標準 (Keccak) 採用全新的海綿結構(Sponge Construction),作為 SHA-2 的安全備援防線。

四、 Java 中的實作範例

在 Java 中,雜湊函數由 JCA 的核心 Engine Class java.security.MessageDigest 提供支援。

Java MessageDigest 標準實作範例

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class HashDemo {
    public static void main(String[] args) throws Exception {
        String inputText = "Hello";

        // 1. 取得 SHA-256 與 SHA3-256 引擎實體 (Engine Class)
        MessageDigest sha2Digest = MessageDigest.getInstance("SHA-256");
        MessageDigest sha3Digest = MessageDigest.getInstance("SHA3-256");

        // 2. 傳入資料位元組並計算雜湊值
        byte[] sha2hashBytes = sha2Digest.digest(inputText.getBytes(StandardCharsets.UTF_8));
        byte[] sha3hashBytes = sha3Digest.digest(inputText.getBytes(StandardCharsets.UTF_8));

        // 3. 轉為十六進位 (Hex String) 表示
        String sha2HexResult = bytesToHex(sha2hashBytes);
        String sha3HexResult = bytesToHex(sha3hashBytes);

        System.out.println("輸入明文: " + inputText);
        System.out.println("SHA-256 雜湊值 (" + sha2hashBytes.length * 8 + " bits): " + sha2HexResult);
        System.out.println("SHA3-256 雜湊值 (" + sha3hashBytes.length * 8 + " bits): " + sha3HexResult);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}


上一篇
Day07 - 現代密碼學基礎 -- 亂數產生器 (RNG)
系列文
我是Java工程師,關於密碼學我想懂的不多9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言